package no.ntnu.idi.deid.patternmatching.search.dictionary.lucene;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class IndexBuilder {
	
	private String filesToIndex;
	private String indexDirectory;

	// konstanter
	public static final String FIELD_CONTENTS = "contents";
	public static final String FIELD_TYPE = "type";
	public static final String DICTIONARY_TYPE_INDICATOR = "#CATEGORYTAG";

	private ArrayList<File> fileQueue = new ArrayList<File>();

	public IndexBuilder(String filesToIndex,String indexDirectory) {
		this.filesToIndex = filesToIndex;
		this.indexDirectory = indexDirectory;
		createIndex();	
	}
	
	public static IndexBuilder buildIndex(String filesToIndex, String indexDirectory) {
		return new IndexBuilder(filesToIndex, indexDirectory);
	}

	public void createIndex() {
		NewLineAnalyzer analyzer = new NewLineAnalyzer(Version.LUCENE_41);
		FSDirectory index;
		try {
			index = FSDirectory.open(new File(indexDirectory));
			IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_41, analyzer);
			IndexWriter indexWriter = new IndexWriter(index, config); //Lager en indexwriter, som gjør det mulig å lage indexen
			indexWriter.deleteAll(); //Sletter indeksen som allerde fins i mappa
			
			indexDirectory(indexWriter,filesToIndex);
			indexWriter.close();
			index.close();
		} catch (IOException e) {
			System.err.println("Unable to build index "+indexDirectory);
			e.printStackTrace();
		}
		analyzer.close();

	}
	
	private void indexDirectory(IndexWriter writer, String directoryName) throws IOException {
		addFiles(new File(directoryName)); //legger til filene osm skal indekseres i filkøen 
		for (File file : fileQueue) {//Traverserer filkøen
			String type = getType(file);
			FileReader filereader = null;
			try {	
				//Legger til hver fil som et dokument, med 3 felter. Her må type også inkluderes.
				Document document = new Document();
				filereader = new FileReader(file);
				
				//Legger til forskjellige felter i dokumentet, de kan søkes på hver for seg.
				document.add(new TextField(FIELD_CONTENTS, filereader)); //legger til innholdet i ordbøkene
				document.add(new StringField(FIELD_TYPE, type, Field.Store.YES)); //legger til type

				writer.addDocument(document);
//				System.out.println("Added: " + file);
			} catch (Exception e) {
				e.printStackTrace();
				System.err.println("Could not add: " + file);
			} finally {
				filereader.close();
			}
		}
	}
	
	private String getType(File file) {
		String line = null;
		String returnstring = file.getName() + ": undefined categorytag";
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			line = br.readLine();
			if (line.startsWith(DICTIONARY_TYPE_INDICATOR)) {
				returnstring = line.substring(DICTIONARY_TYPE_INDICATOR.length()+1, line.length()).trim();
				br.close();
			}
			else {
				System.err.println("IndexBuilder.java:"+line+ " need to start with" + DICTIONARY_TYPE_INDICATOR);
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return returnstring;
	}
	
	private void addFiles(File file) {
		if (!file.exists()) {
			System.err.println(file + " does not exist.");
		}
		else if (file.isDirectory()) {
			for (File f : file.listFiles()) {
				addFiles(f);
			}
		} else {
			String filename = file.getName();
			if (filename.endsWith(".txt")) {
				fileQueue.add(file);
			} 
			else {
				System.err.println("Skipped " + filename);
			}
		}
	}
}
